home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / RATIONAL.H < prev    next >
C/C++ Source or Header  |  1992-11-10  |  16KB  |  420 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // Texas Instruments Incorporated provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. //
  13. // Created: MBN 10/25/89 -- Initial design and implementation
  14. // Updated: MBN 03/04/90 -- Added execption for DIVIDE_BY_ZERO
  15. // Updated: MJF 07/31/90 -- Added terse print
  16. // Updated: DLS 04/01/91 -- New lite version
  17. // Updated: JAM 08/10/92 -- removed 'inline' from friend declarations
  18. // Updated: JAM 08/11/92 -- removed DOS specifics, stdized #includes
  19. //
  20. // The Rational class  implements rational numbers  and arithmetic.  A Rational
  21. // object has the same precision and range of values as the built-in type long.
  22. // Implicit conversion to the system defined types short, int, long, float, and
  23. // double is supported by  overloaded  operator member functions.  Although the
  24. // Rational class makes judicous use  of inline  functions and  deals only with
  25. // integral values, the user  is warned that  the Rational  integer  arithmetic
  26. // class is still considerably slower than the built-in  integer data types. If
  27. // the range  of values  anticipated will  fit into a  built-in  type, use that
  28. // instead.
  29. //
  30. // The  Rational class implements   common  arithmetic exception  handling  and
  31. // provides  the  application  with  support for  detecting  negative infinity,
  32. // positive  infinity,  overflow, and underflow  as a result of some arithmetic
  33. // expression.  If  one of  these conditions or  an  attempt to  convert from a
  34. // Rational with no value to a built-in type is detected, an Error exception is
  35. // raised. The application programmer can provide an  exception handler to take
  36. // care of this problem. If  no such handler is  available, an error message is
  37. // printed and the application terminates.
  38. //
  39. // The Rational class requires several constants be defined to insure precision
  40. // and accuracy   of conversion.  The   preprocessor  symbols MINSHORT, MININT,
  41. // MINLONG, MAXSHORT, MAXINT, and MAXLONG  are calculated  in the <misc.h>
  42. // header file  via various  bit  manipulation  macros. The  symbols  MINFLOAT,
  43. // MINDOUBLE,  MAXFLOAT,  and MAXDOUBLE  are  system dependent  and cannot   be
  44. // calculated.  Most systems typically have  values  for these constants in the
  45. // system header  file <values.h>.  Values  for a  specific  machine should  be
  46. // copied into the <misc.h> header file as necessary.
  47. //
  48. // The private data section of the Rational class contains two long data slots,
  49. // one for the numerator and one for the denominator.   The Rational class also
  50. // contains a private  data slot  providing arithmetic exception status.  There
  51. // are five constructors for the Rational class.  The first is  a simple inline
  52. // constructor that initializes the state and private  data slots.   The second
  53. // takes two integers (short, int, or long) and uses them as the  initial value
  54. // for  the  object.   The second  argument is  optional  and if  not supplied,
  55. // defaults to one.  The third  takes two longs  and  uses  them as the initial
  56. // value for the object.  The second argument is optional and  if not supplied,
  57. // defaults to one.  The  fourth takes a  double  and  calculates an equivalent
  58. // normalized rational.  Finally, the fifth takes  a const reference to another
  59. // Rational object and duplicates its state and value.
  60. //
  61. // The Rational class  provides overloaded operators for addition, subtraction,
  62. // multiplication,  division, and  modulus.  Also  available are inequality and
  63. // equality,  assignment, increment, decrement,  unary  minus, ones-complement,
  64. // output, less than, greater than,  less than or  equal, and greater  than  or
  65. // equal.  Methods to get the numerator  and denominator, invert, calculate the
  66. // floor  and ceiling, truncate,  and round are  supported. Finally,  five type
  67. // conversion functions to short, int, long, float, and double are provided.
  68.  
  69. #ifndef RATIONAL_H                // If no Rational definition
  70. #define RATIONAL_H                // define the Rational symbol
  71.  
  72. #include <iostream.h>
  73.  
  74. #ifndef MISCELANEOUSH            // If we have not included this file
  75. #include <misc.h>        // Include miscellaneous useful defs
  76. #endif
  77.  
  78.  
  79. class CoolRational {
  80. public:
  81.   inline CoolRational ();            // Simple constructor
  82.   CoolRational (long, long d = 1);        // Constructor with longs
  83.   CoolRational (const CoolRational&);        // Copy constructor
  84.   inline ~CoolRational();            // destructor
  85.   
  86.   inline long numerator () const;        // Get the numerator
  87.   inline long denominator () const;        // Get the denominator
  88.   inline N_status status () const;        // Return Number status
  89.   
  90.   inline CoolRational& operator= (const CoolRational&);    // Overload assignment
  91.   inline Boolean operator== (const CoolRational&) const; // Overload equality
  92.   inline Boolean operator!= (const CoolRational&) const; // Overload inequality
  93.   
  94.   inline CoolRational operator-() const;    // Unary minus operator
  95.   inline Boolean operator!() const;        // Unary not operator
  96.   
  97.   CoolRational& operator+= (const CoolRational&); // Overload plus/assign
  98.   CoolRational& operator-= (const CoolRational&); // Overload minus/assign
  99.   CoolRational& operator*= (const CoolRational&); // Overload multiply/assign
  100.   CoolRational& operator/= (const CoolRational&); // Overload divide/assign
  101.   CoolRational& operator%= (const CoolRational&); // Overload modulus/assign
  102.   
  103.   friend CoolRational operator+ (const CoolRational&, const CoolRational&);
  104.   friend CoolRational operator- (const CoolRational&, const CoolRational&);
  105.   friend CoolRational operator* (const CoolRational&, const CoolRational&);
  106.   friend CoolRational operator/ (const CoolRational&, const CoolRational&);
  107.   friend CoolRational operator% (const CoolRational&, const CoolRational&); 
  108.  
  109.   inline CoolRational& operator++ ();        // Overload increment
  110.   inline CoolRational& operator-- ();        // Overload decrement
  111.   
  112.   Boolean operator< (const CoolRational&) const; // Overload less than
  113.   inline Boolean operator<= (const CoolRational&) const; // Overload less/equal
  114.   Boolean operator> (const CoolRational&) const;     // Overload greater than
  115.   inline Boolean operator>= (const CoolRational&) const; // Overload greater/equal
  116.   
  117.   friend ostream& operator<< (ostream&, const CoolRational&); // Output ref
  118.   friend ostream& operator<< (ostream&, const CoolRational*); // Output ptr
  119.   
  120.   void print(ostream&);                // Terse print
  121.   
  122.   CoolRational& invert ();            // Invert the rational number
  123.   inline long floor () const;            // Truncate towards -infinity
  124.   inline long ceiling () const;            // Truncate towards +infinity
  125.   inline long truncate () const;        // Truncate towards zero
  126.   long round () const;                // Truncate to nearest integer
  127.   
  128.   operator short ();                // Implicit conversion
  129.   operator int ();                // Implicit conversion
  130.   operator long ();                // Implicit conversion
  131.   operator float ();                // Implicit conversion
  132.   inline operator double ();            // Implicit conversion
  133.  
  134. private:
  135.   long num;                    // Numerator portion
  136.   long den;                    // Denominator portion
  137.   N_status state;                // Exception status
  138.   
  139.   long gcd (long, long);            // Calculate GCD
  140.   void normalize ();                // Normalize num/den 
  141.   void minus_infinity (const char*) const;    // Raise - infinity exception
  142.   void plus_infinity (const char*) const;    // Raise + infinity exception
  143.   void overflow (const char*) const;        // Raise overflow error
  144.   void underflow (const char*) const;        // Raise underflow error
  145.   void divide_by_zero (const char*) const;    // Raise divide by zero error
  146. };
  147.  
  148.  
  149. // Rational -- Simple constructor
  150. // Input:      None
  151. // Output:     None
  152.  
  153. inline CoolRational::CoolRational () {
  154.   this->num = this->den = 0;            // Initialize data slots
  155.   this->state = N_OK;                // Set status to OK
  156. }
  157.  
  158.  
  159. // Rational -- Copy constructor
  160. // Input:      Reference to rational object
  161. // Output:     None
  162.  
  163. inline CoolRational::CoolRational (const CoolRational& r) {
  164.   this->num = r.num;                // Set numerator
  165.   this->den = r.den;                // Set denominator
  166.   this->state = r.state;            // Set state
  167. }
  168.  
  169. // ~Rational -- Destructor does nothing
  170.  
  171. inline CoolRational::~CoolRational() {}
  172.  
  173. // numerator -- Return the numerator portion of the rational
  174. // Input:       None
  175. // Output:      Numerator of rational
  176.  
  177. inline long CoolRational::numerator () const {
  178.   return this->num;                // Return numerator
  179. }
  180.  
  181.  
  182. // denominator -- Return the denominator portion of the rational
  183. // Input:         None
  184. // Output:        Denominator of rational
  185.  
  186. inline long CoolRational::denominator () const {
  187.   return this->den;                // Return denominator
  188. }
  189.  
  190.  
  191. // status -- Return the status of Number
  192. // Input:    None
  193. // Output:   N_status enum value
  194.  
  195. inline N_status CoolRational::status () const {
  196.   return this->state;
  197. }
  198.  
  199.  
  200. // operator= -- Overload the assignment operator for the Rational class
  201. // Input:       Reference to rational object
  202. // Output:      Reference to updated rational object
  203.  
  204. inline CoolRational& CoolRational::operator= (const CoolRational& r) {
  205.   this->num = r.num;                // Set numerator
  206.   this->den = r.den;                // Set denominator
  207.   this->state = r.state;            // Set state
  208.   return *this;                    // Return reference
  209. }
  210.   
  211.  
  212. // operator== -- Overload the equality operator for the rational class
  213. // Input:        Reference to rational object
  214. // Output:       TRUE/FALSE
  215.  
  216. inline Boolean CoolRational::operator== (const CoolRational& r) const {
  217.   return (this->num == r.num && this->den == r.den);
  218. }
  219.  
  220.  
  221. // operator!= -- Overload the inequality operator for the Rational class
  222. // Input:        Reference to a constant rational object
  223. // Ouput:        TRUE/FALSE
  224.  
  225. inline Boolean CoolRational::operator!= (const CoolRational& r) const {
  226.   return !(*this == r);
  227. }
  228.  
  229.  
  230. // operator< -- Overload operator less than for the rational class
  231. // Input:       Reference to rational number
  232. // Output:      TRUE/FALSE
  233.  
  234. inline Boolean CoolRational::operator< (const CoolRational& r) const {
  235.   if (this->den == r.den)            // If same denominator
  236.     return (this->num < r.num);            // Return less than sense
  237.   else                        // Else calculate common denom.
  238.     return ((this->num * r.den) < (this->den * r.num));    // And return state
  239. }
  240.  
  241.  
  242. // operator> -- Overload operator greater than for the rational class
  243. // Input:       Reference to rational number
  244. // Output:      TRUE/FALSE
  245.  
  246. inline Boolean CoolRational::operator> (const CoolRational& r) const {
  247.   if (this->den == r.den)            // If same denominator
  248.     return (this->num > r.num);            // Return greater than sense 
  249.   else                        // Else calculate common denom.
  250.     return ((this->num * r.den) > (this->den * r.num));    // And return state
  251. }
  252.  
  253.  
  254. // operator<= -- Overload the less than or equal to operator for rational
  255. // Input:        Reference to a constant rational object
  256. // Output:       TRUE/FALSE
  257.  
  258. inline Boolean CoolRational::operator<= (const CoolRational& r) const {
  259.   return !(*this > r);
  260. }
  261.  
  262.  
  263. // operator>= -- Overload the greater than or equal to operator for rational
  264. // Input:        Reference to a constant rational object
  265. // Output:       TRUE/FALSE
  266.  
  267. inline Boolean CoolRational::operator>= (const CoolRational& r) const {
  268.   return !(*this < r);
  269. }
  270.  
  271.  
  272. // operator<< -- Overload the output operator for a reference to a rational
  273. // Input:        Reference to an ostream
  274. // Output:       Reference to an ostream
  275.  
  276. inline ostream& operator<< (ostream& os, const CoolRational& r) {
  277.   os << r.num << "/" << r.den;            // Output rational number
  278.   return os;                    // Return ostream reference
  279. }
  280.  
  281.  
  282. // operator<< -- Overload the output operator for a pointer to a rational
  283. // Input:        Ostream reference, pointer to a rational object
  284. // Output:       Ostream reference
  285.  
  286. inline ostream& operator<< (ostream& os, const CoolRational* r) {
  287.   return operator<< (os, *r);
  288. }
  289.  
  290.  
  291. // operator- -- Overload the unary minus operator for the Rational class
  292. // Input:       None
  293. // Output:      Negated rational value
  294.  
  295. inline CoolRational CoolRational::operator- () const {
  296.   CoolRational r (-this->num, this->den);    // Get negative value
  297.   return r;                    // Return deferenced pointer
  298. }
  299.  
  300.  
  301. // operator! -- Overload the negation operator for the Rational class
  302. // Input:       None
  303. // Output:      TRUE/FALSE
  304.  
  305. inline Boolean CoolRational::operator! () const {
  306.   return ((this->num == 0) ? TRUE : FALSE);    // Return logical state
  307. }
  308.  
  309.  
  310. // operator++ -- Overload the increment operator for the Rational class
  311. // Input:        None
  312. // Output:       Reference to updated rational object
  313.  
  314. inline CoolRational& CoolRational::operator++ () {
  315.   this->num += this->den;            // Increment numerator
  316.   return *this;                    // Return updated object
  317. }
  318.   
  319.  
  320. // operator-- -- Overload the decrement operator for the Rational class
  321. // Input:        None
  322. // Output:       Reference to updated rational object
  323.  
  324. inline CoolRational& CoolRational::operator-- () {
  325.   this->num -= this->den;            // Decrement numerator
  326.   return *this;                    // Return updated object
  327. }
  328.  
  329.  
  330. // truncate -- Converts rational value by truncating towards zero
  331. // Input:      None
  332. // Output:     long truncated value
  333.  
  334. inline long CoolRational::truncate () const {
  335.   return (long) (this->num / this->den);    // Return truncated rational
  336. }
  337.  
  338.  
  339. // floor -- Converts rational value by truncating towards negative infinity
  340. // Input:   None
  341. // Output:  long value of truncated rational
  342.  
  343. inline long CoolRational::floor () const {
  344.   long temp = this->truncate ();        // Get truncated value
  345.   return ((this->num < 0.0 && (-(this->num%this->den) > 0.5*this->den)) ?
  346.       (temp - 1) : temp);
  347. }
  348.  
  349.  
  350. // ceiling -- Converts rational value by truncating towards positive infinity
  351. // Input:     None
  352. // Output:    long value of truncated rational
  353.  
  354. inline long CoolRational::ceiling () const {
  355.   long temp = this->truncate ();        // Get truncated value
  356.   return ((this->num > 0.0 && ((this->num%this->den) > 0.5*this->den)) ?
  357.       (temp + 1) : temp);
  358. }
  359.  
  360.  
  361. // operator+ -- Overload the addition operator for rational
  362. // Input:       Reference to two rational numbers
  363. // Output:      A new rational number
  364.  
  365. inline CoolRational operator+ (const CoolRational& r1, const CoolRational& r2) {
  366.   CoolRational result(r1);
  367.   result += r2;
  368.   return result;
  369. }
  370.  
  371. // operator- -- Overload the subtraction operator for rational
  372. // Input:       Reference to two rational numbers
  373. // Output:      A new rational number
  374.  
  375. inline CoolRational operator- (const CoolRational& r1, const CoolRational& r2) {
  376.   CoolRational result(r1);
  377.   result -= r2;
  378.   return result;
  379. }
  380.  
  381. // operator* -- Overload the multiplication operator for rational
  382. // Input:       Reference to two rational numbers
  383. // Output:      A new rational number
  384.  
  385. inline CoolRational operator* (const CoolRational& r1, const CoolRational& r2) {
  386.   CoolRational result(r1);
  387.   result *= r2;
  388.   return result;
  389. }
  390.  
  391. // operator/ -- Overload the division operator for rational
  392. // Input:       Reference to two rational numbers
  393. // Output:      A new rational number
  394.  
  395. inline CoolRational operator/ (const CoolRational& r1, const CoolRational& r2) {
  396.   CoolRational result(r1);
  397.   result /= r2;
  398.   return result;
  399. }
  400.  
  401. // operator% -- Overload the remainder operator for rational
  402. // Input:       Reference to two rational numbers
  403. // Output:      A new rational number
  404.  
  405. inline CoolRational operator% (const CoolRational& r1, const CoolRational& r2) {
  406.   CoolRational result(r1);
  407.   result %= r2;
  408.   return result;
  409. }
  410.  
  411. // operator double -- Implicit conversion operator from Rational to a double
  412. // Input:             None
  413. // Output:            Double value equivalent to rational
  414.  
  415. inline CoolRational::operator double () {
  416.   return ((double)this->num)/((double)this->den);     // Double answer
  417. }
  418.  
  419. #endif RATIONAL_H                    // End RATIONALH
  420.